package com.sohoometer.heatMeter.service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.nari.baseinfo.dao.IHeatMeterDao;
import com.nari.coreframe.service.GenericServiceImpl;
import com.nari.heatshare.dao.IHeatMeterDataGatherDao;
import com.nari.heatshare.model.IHeatMeterDataGather;
import com.sohoometer.heatMeter.bean.HeatMeterDataExceptionQuery;
import com.sohoometer.heatMeter.bean.HeatMeterDataExceptionResult;
import com.sohoometer.heatMeter.bean.HeatMeterDataExceptionType;
import com.sohoometer.heatMeter.dao.HeatMeterDataExceptionQueryDao;
import com.sohoometer.heatMeter.dao.HeatMeterDataExceptionResultDao;

@Service("heatMeterDataExceptionQueryService")
public class HeatMeterDataExceptionQueryServiceImpl extends
		GenericServiceImpl<HeatMeterDataExceptionQuery, String> implements
		HeatMeterDataExceptionQueryService {
	@Autowired
	private IHeatMeterDao  iIHeatMeterDao = null;
	@Autowired
	private IHeatMeterDataGatherDao iHeatMeterDataGatherDao = null;
	@Autowired
	private HeatMeterDataExceptionQueryDao  heatMeterDataExceptionQueryDao = null;
	@Autowired
	private HeatMeterDataExceptionResultDao  heatMeterDataExceptionResultDao = null;
	@Autowired
	private	ThreadPoolTaskExecutor threadPoolTaskExecutor = null;
	@Autowired
	private  HibernateTransactionManager hibernateTxManager = null;
	@Autowired
public HeatMeterDataExceptionQueryServiceImpl(HeatMeterDataExceptionQueryDao heatMeterDataExceptionQueryDao) {
	this.setiGenericDao(heatMeterDataExceptionQueryDao);
	this.heatMeterDataExceptionQueryDao = heatMeterDataExceptionQueryDao;
}	
	
	@Override
	public void addQuery(HeatMeterDataExceptionQuery query) throws Exception {
		String id =heatMeterDataExceptionQueryDao.saveEntity(query);
		dealWithQuery(query, id);
	}

	
	public void  dealWithQuery(final HeatMeterDataExceptionQuery query,final String id) {
		//处理档案中的热量表 得到热量表基本信息
		//是否有自定义异常
		Runnable  task = new Runnable() {
			@Override
			public void run() {
				//事务
				DefaultTransactionDefinition  def = new DefaultTransactionDefinition();
				def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
				TransactionStatus transaction = hibernateTxManager.getTransaction(def);
				if(query.getUnUpload()!=null&&query.getUnUpload()) {
					dealWithUnUpload(query,id); //进行选择是否查询未上传
				}
				try {
					dealWithDataException(query,id);
				} catch (Exception e) {
					e.printStackTrace();
				}
				uploadState(id);
				hibernateTxManager.commit(transaction);
			}
		};
		threadPoolTaskExecutor.execute(task,AsyncTaskExecutor.TIMEOUT_IMMEDIATE);
		//提交事务
	}

	private void uploadState(String id) {
		try {
			HeatMeterDataExceptionQuery query = heatMeterDataExceptionQueryDao.queryEntityById(id);
			query.setIsDone(Boolean.TRUE);
			heatMeterDataExceptionQueryDao.saveOrUpdateEntity(query);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void dealWithDataException(HeatMeterDataExceptionQuery query,String id) throws Exception {
		ArrayList<String> heatmeters = getHeatMeterNos(query);
		for(String meterNo : heatmeters) { 
			List<IHeatMeterDataGather> meterData = iHeatMeterDataGatherDao.queryMeterData(meterNo, query.getStartRecordTime(), query.getEndRecordTime());
			dealWithDatas(meterNo,meterData,query,id);
		}
	}

	private void dealWithDatas(String meterNo,List<IHeatMeterDataGather> meterData,HeatMeterDataExceptionQuery query, String id) {
		if(meterData==null||meterData.size()<1) return;
		//遍历数据,将数据分别按照异常种类进行数据筛选
		for(IHeatMeterDataGather data : meterData){
			if(query.getDataException()!=null&&query.getDataException()) {
				dealWithSingleMeterDataException(data,id);
			}
			dealWtihSelfDefine(data,query,id);
		}
	}
	
/**
 * 
 * 处理自定义异常
 * 
 * */
	private void dealWtihSelfDefine(IHeatMeterDataGather data,HeatMeterDataExceptionQuery query, String id) {
		boolean met = false;
		int exceptionType = 0;
		//累计热量  MWH 1  KWH 2 GJ  3 换算单位为1000
		double sumHeat = query.getSumHeat();//查询累计热量
		//只有开始查询时才真正查询
		boolean sumHeatMet = true;
		if(sumHeat!=0) {
			Integer sumHeatUnit = query.getSumHeatUnit();//查询累计热量单位
			String sumHeatCom = query.getSumHeatCom();//查询累计热量比较符
			Integer sumHeatUnitRecord = data.getSumHeatUnit();
			double sumHeatRecord = data.getSumHeat(); //累计热量实际值
			Double queryValue = getHeatUnitValue(sumHeatUnit,sumHeat );//查询值
			Double recordValue = getHeatUnitValue(sumHeatUnitRecord, sumHeatRecord);
			sumHeatMet=ifMet(sumHeatCom, queryValue, recordValue);
			if(sumHeatMet) {
				exceptionType+=HeatMeterDataExceptionType.SUMHEAT_EXCEPTION;//热量表总热量异常
			}
		}
		//累计流量   m3/h  1 2 dm3;h     cm3;h  3立方米,立方厘米，立方分米,  1立方米=1000立方分米 1立方分米=1000立方厘米
		double instantFlow = query.getInstantFlow();
		boolean instantFlowMet = true;
		if(instantFlow!=0) {
			String instantFlowCom = query.getInstantFlowCom();
			Integer instantFlowUnit = query.getInstantFlowUnit();//查询单位
			Integer instantFlowUnitRecord = data.getInstantFlowUnit();//真实瞬时流量
			double instantFlowRecord = data.getInstantFlow();//瞬时流量单位
			Double queryValue = getUnitValue(instantFlowUnit, instantFlow, 1000);
			Double recordValue = getUnitValue(instantFlowUnitRecord, instantFlowRecord, 1000);
			instantFlowMet = ifMet(instantFlowCom, queryValue, recordValue);
			if(instantFlowMet) {
				//瞬时流量异常
				exceptionType+=HeatMeterDataExceptionType.INSTANTFLOW_EXCEPTION;
			}
		}
		//供水温度
		boolean supplyTemperatureMet = true;
		double supplyTemperature = query.getSupplyTemperature();
		if(supplyTemperature!=0) {
			String supplyTemperatureCom = query.getSupplyTemperatureCom();
			double supplyTemperatureRecord = data.getSupplyTemperature();
			supplyTemperatureMet = ifMet(supplyTemperatureCom, supplyTemperature, supplyTemperatureRecord);
			if(supplyTemperatureMet) {
				exceptionType+=HeatMeterDataExceptionType.TEMPEXCEPTION_SUPPLYWATER;
			}
		}
		//回水温度
		double backTemperature = query.getBackTemperature();
		boolean backTemperatureMet = true;
		if(backTemperature!=0) {
			String backTemperatureCom = query.getBackTemperatureCom();
			double backTemperatureRecord = data.getBackTemperature();
			backTemperatureMet = ifMet(backTemperatureCom, backTemperature, backTemperatureRecord);
			if(backTemperatureMet) {
				exceptionType+=HeatMeterDataExceptionType.TEMPEXCEPTION_BACKWATER;
			}
		}
		//温差
		double temperatureDiff = query.getTemperatureDiff();
		boolean tempDiffMet = true;
		if(temperatureDiff!=0) {
			String temperatureDiffCom = query.getTemperatureDiffCom();
			double temperatureDiffRecord = data.getTemperatureDiff();
			tempDiffMet = ifMet(temperatureDiffCom, temperatureDiff, temperatureDiffRecord);
			if(tempDiffMet) {
				//温差自定义异常
				exceptionType+=HeatMeterDataExceptionType.TEMPEXCEPTION__TEMPDIFF;
			}
			}
		met = sumHeatMet&instantFlowMet&supplyTemperatureMet&backTemperatureMet&tempDiffMet;
		if(met&&exceptionType>0) {
			//满足自定义异常
			exceptionType+=HeatMeterDataExceptionType.SELF_EXCEPTION;
			//自定义异常的WrongInfo 默认保存为2
			HeatMeterDataExceptionResult result = getResult(data, id, exceptionType, "2");
			saveResult(result);
		}
	}
	/**
	 * 体积单位转换 将大单位统一换算成小单位
	 * */
	private  Double getUnitValue(Integer i ,Double value,double unit){
		Double result = null;
		switch (i) {
		case 1: result = value*unit*unit; //使用乘法来进行换算 都换算成最低的单位
			break;
		case 2:result=value*unit;//使用乘法都换算成最低的单位 
			break;
		case 3:result = value;
			break;
		default:
			break;
		}
		return result;
	}
	
	/**
	 * 热量单位转换 将大单位统一换算成小单位
	 * */
	private  Double getHeatUnitValue(Integer i ,Double value){
		Double result = null;
		//将数值都换成KWH进行
		switch (i) {
		case 1: result = value*1000; //使用乘法来进行换算 都换算成最低的单位
			break;
		case 2:result=value;//使用乘法都换算成最低的单位 
			break;
		case 3:result = value*278;
			break;
		default:
			break;
		}
		return result;
	}
	
	/*
	 * 某一查询项与真实读数条件是否满足
	 * **/
private boolean ifMet(String queryCom, Double queryreadNum,
			double readNum) {
		boolean flag = false;
		String readNumCom = queryCom;
		if("s".equals(readNumCom)) {
			flag = readNum<queryreadNum;
		}
		if("b".equals(readNumCom)) {
			flag = readNum>queryreadNum;
		}
		return flag;
	}
	
	/**
	 * 处理单条热量表数据异常情况
	 * 根据热量表数据的 wrongInfo 进行判断0
	1
	9999
	8710
	0400
	0800
	0100
	0000
	0200
	无
	0801
	0201
	E
	Null
	0A01
	0101
	0700
	0600
	0001
	 * 
	 * */
	private void dealWithSingleMeterDataException(IHeatMeterDataGather data, String id) {
		String wrongInfo = data.getWrongInfo();
		if(StringUtils.isBlank(wrongInfo)||"0".equals(wrongInfo)) return; //如果错误信息为0 则为正常
		HeatMeterDataExceptionResult result = getResult(data,id,HeatMeterDataExceptionType.DATA_UPLOADEXCEPTION,wrongInfo);
		saveResult(result);
	}

	private HeatMeterDataExceptionResult getResult(IHeatMeterDataGather data,String id, int dATA_UPLOADEXCEPTION, String wrongInfo) {
		HeatMeterDataExceptionResult  result = new HeatMeterDataExceptionResult();
		result.setQueryid(id);
		result.setDataid(data.getId());
		result.setWrongInfo(wrongInfo);
		result.setExceptionType(dATA_UPLOADEXCEPTION);
		result.setMeterNo(data.getMeterNo());
		result.setSupplyTemperature(data.getSupplyTemperature());
		result.setBackTemperature(data.getBackTemperature());
		result.setRecordTime(data.getRecordTime());
		result.setSumHeat(data.getSumHeat());
		result.setSumHeatUnit(data.getSumHeatUnit());
		result.setInstantFlow(data.getInstantFlow());
		result.setInstantFlowUnit(data.getInstantFlowUnit());
		double supplyTemperature = data.getSupplyTemperature();
		double backTemperature = data.getBackTemperature();
		//设置温差 圆整一下
		MathContext mathContext = new MathContext(3);//保留小数点后一位
		double temdiff = new BigDecimal(supplyTemperature-backTemperature).round(mathContext).doubleValue();
		result.setTemperatureDiff(temdiff);
		return result;
	}

	private ArrayList<String> getHeatMeterNos(HeatMeterDataExceptionQuery query) throws Exception {
		return iIHeatMeterDao.queryHeatMeterNos(query.getProjectID(), query.getCommunityID(), query.getBuildingID(), null, query.getMeterNo(), null);
	}
	
	/**
	 *   保存查询结果
	 * */
	private void saveResult(HeatMeterDataExceptionResult result) {
		try {
			heatMeterDataExceptionResultDao.saveEntity(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 处理查询中的未上传部分
	 * 未上传处理逻辑: 从查询终止日期之前的一段时间内是否上传，
	 * 如果没有上传，查询最后一次上传时间,如果最后一次上传时间大于查询终止时间，则是已上传。
	 * @throws Exception 
	 * */
	private void dealWithUnUpload(HeatMeterDataExceptionQuery query, String id)  {
		ArrayList<String> heatMeterNos = null;
		try {
			heatMeterNos = getHeatMeterNos(query);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		if(heatMeterNos==null||heatMeterNos.size()<1) return;
		Date endTime = query.getEndRecordTime();
		int day = query.getEndDay();
		if(day<0) return;
		Calendar instance = Calendar.getInstance();
		instance.setTime(endTime);
		instance.roll(Calendar.DAY_OF_YEAR,-day);//回滚相应的天数
		Date startTime = instance.getTime();
		for(String meterNo : heatMeterNos) {
			try {
				List<IHeatMeterDataGather> meterDataWithLimit = iHeatMeterDataGatherDao.queryHeatMeterDataWithLimit(meterNo, startTime, endTime, 1);
				if(meterDataWithLimit!=null&&meterDataWithLimit.size()>0) {continue;}//上传过
				Date lastUploadDate = iHeatMeterDataGatherDao.queryLastUploadDate(meterNo);
				if(lastUploadDate!=null) {
					if(lastUploadDate.after(endTime)) continue;
				}
				//此时说明该数据不符合要求 记录最后一次上传时间
				HeatMeterDataExceptionResult result = new HeatMeterDataExceptionResult();
				result.setMeterNo(meterNo);
				result.setQueryid(query.getId());
				result.setRecordTime(lastUploadDate);
				result.setExceptionType(HeatMeterDataExceptionType.HEATMETER_UNUPLOAD);
				saveResult(result);
			} catch (Exception e) {
				continue;
			}
		}
		//遍历热量表号 进行查询
	}

	@Override
	public void deleteQuery(String id)  throws Exception{
		heatMeterDataExceptionQueryDao.deleteEntityById(id);
		heatMeterDataExceptionResultDao.deleteResultByQueryId(id);
	}
}
